Options & libs
# Turning scientific / Exponential numbers off
options(scipen = 999)
library(tidyverse)
library(tidytuesdayR)
library(ggthemes)
library(glue)
library(scales)
view missing data
Creating & setting custom theme
theme_viny_bright <- function(){
library(ggthemes)
ggthemes::theme_fivethirtyeight() %+replace%
theme(
axis.title = element_text(size = 9),
axis.text = element_text(size = 8),
legend.text = element_text(size = 7),
panel.background = element_rect(fill = "white"),
plot.background = element_rect(fill = "white"),
strip.background = element_blank(),
legend.background = element_rect(fill = NA),
legend.key = element_rect(fill = NA),
plot.title = element_text(hjust = 0.5,
size = 16,
face = "bold"),
plot.subtitle = element_text(hjust = 0.5, size = 10, face = "bold"),
plot.caption = element_text(hjust = 1, size = 8)
)
}
theme_set(theme_viny_bright())
sources:
Inspired from: https://www.youtube.com/watch?v=EHqFDXa-sH4&t=2105s
Loading data
tt <- tt_load("2021-03-02")
tt
EDA
youtube <- tt$youtube
youtube
youtube %>%
mutate_if(is.character, as.factor) %>%
summary()
missing value
naniar::gg_miss_upset(data = youtube)


youtube %>%
count(brand) %>%
mutate(brand = fct_reorder(brand, n)) %>%
ggplot(aes(x = n, y = brand)) +
geom_col()

youtube %>%
ggplot(aes(x = year, fill = brand)) +
geom_bar() +
facet_wrap(~brand) +
guides(x = guide_axis(n.dodge = 2))

youtube %>%
na.omit() %>%
mutate(brand = fct_reorder(brand, view_count)) %>%
ggplot(aes(x = view_count, y = brand)) +
geom_boxplot() +
# geom_jitter(alpha = 0.3) +
scale_x_log10(labels = comma)

youtube %>%
na.omit() %>%
mutate(brand = fct_reorder(brand, view_count)) %>%
ggplot(aes(x = view_count, y = brand)) +
geom_violin(draw_quantiles = c(0.25, 0.5, 0.75)) +
geom_jitter(alpha = 0.3) +
scale_x_log10(labels = comma)

youtube %>%
na.omit() %>%
mutate(brand = fct_reorder(brand, view_count)) %>%
ggplot(aes(x = view_count, y = brand, fill = funny)) +
geom_boxplot() +
# geom_jitter(alpha = 0.3) +
scale_x_log10(labels = comma)

youtube %>%
na.omit() %>%
mutate(brand = fct_reorder(brand, view_count)) %>%
ggplot(aes(x = view_count, y = brand, fill = use_sex)) +
geom_boxplot() +
# geom_jitter(alpha = 0.3) +
scale_x_log10(labels = comma)

youtube %>%
pivot_longer(names_to = "ads_category", values_to = "true_false",
cols = funny:use_sex)
popular categories in brands
youtube %>%
pivot_longer(names_to = "ads_category", values_to = "true_false",
cols = funny:use_sex) %>%
filter(true_false == "TRUE") %>%
ggplot(aes(y = ads_category, x = view_count)) +
geom_col() +
facet_wrap(~brand)

log of view_count
youtube %>%
pivot_longer(names_to = "ads_category", values_to = "true_false",
cols = funny:use_sex) %>%
filter(true_false == "TRUE") %>%
ggplot(aes(y = fct_reorder(ads_category, view_count),
x = view_count)) +
geom_col() +
facet_wrap(~brand) +
scale_x_log10()

reorder_within by view_count
youtube %>%
na.omit() %>%
pivot_longer(names_to = "ads_category", values_to = "true_false",
cols = funny:use_sex) %>%
filter(true_false == "TRUE",
view_count > 10000) %>%
group_by(brand, ads_category, view_count) %>%
summarise(view_count = sum(view_count)) %>%
ungroup() %>%
mutate_if(is.character, factor) %>%
mutate(ads_category = reorder_within(x = ads_category, by = view_count, within = brand)) %>%
ggplot(aes(y = ads_category, x = view_count)) +
geom_col() +
facet_wrap(~brand, scales = "free_y") +
scale_y_reordered() +
theme(axis.text.x = element_text(angle = 90)) +
scale_x_continuous(labels = unit_format(unit = "M", scale = 1e-6))

gathered_categories <- youtube %>%
na.omit() %>%
gather(ads_category, true_false, funny:use_sex)
gathered_categories
view_count by pct
gathered_categories %>%
filter(true_false == "TRUE",
) %>% # view_count > 10000
group_by(brand, ads_category) %>%
summarise(view_count = sum(view_count)) %>%
group_by(brand) %>%
mutate(pct = view_count / sum(view_count)) %>%
# mutate_if(is.character, factor) %>%
mutate(ads_category = reorder_within(x = ads_category, by = pct, within = brand)) %>%
ggplot(aes(y = ads_category, x = view_count)) +
geom_col() +
facet_wrap(~brand, scales = "free_y") +
scale_y_reordered() +
theme(axis.text.x = element_text(angle = 90)) +
scale_x_continuous(labels = unit_format(unit = "M", scale = 1e-6))

by pct
wrapping axis text using str_wrap() from: https://stackoverflow.com/questions/21878974/wrap-long-axis-labels-via-labeller-label-wrap-in-ggplot2
gathered_categories %>%
filter(true_false == "TRUE",
) %>% # view_count > 10000
group_by(brand, ads_category) %>%
summarise(view_count = sum(view_count)) %>%
group_by(brand) %>%
mutate(pct = view_count / sum(view_count),
ads_category = str_replace_all(ads_category,"_"," "),
ads_category = str_wrap(ads_category, width = 10)) %>%
# mutate_if(is.character, factor) %>%
mutate(ads_category = reorder_within(x = ads_category, by = pct, within = brand)
) %>%
ggplot(aes(y = ads_category, x = pct)) +
geom_col() +
facet_wrap(~brand, scales = "free_y") +
scale_y_reordered() +
theme(axis.text.x = element_text(angle = 90)) +
scale_x_continuous(labels = percent)

pct+view_count labels
Adding view_count to axis text in above chart
gathered_categories %>%
filter(true_false == "TRUE",
) %>% # view_count > 10000
group_by(brand, ads_category) %>%
summarise(view_count = sum(view_count)) %>%
group_by(brand) %>%
mutate(pct = view_count / sum(view_count),
ads_category = str_replace_all(ads_category,"_"," "),
ads_category = paste(ads_category,view_count),
ads_category = str_wrap(ads_category, width = 10)) %>%
# mutate_if(is.character, factor) %>%
mutate(ads_category = reorder_within(x = ads_category, by = pct, within = brand)
) %>%
ggplot(aes(y = ads_category, x = pct)) +
geom_col() +
facet_wrap(~brand, scales = "free_y") +
scale_y_reordered() +
theme(axis.text.x = element_text(angle = 90)) +
scale_x_continuous(labels = percent)

test_set = data.frame(x = c("label", "long label", "very,_very_long_label"),
y = c(10, 15, 20))
test_set$newx = str_wrap(test_set$x, width = 10)
ggplot(test_set, aes(newx, y)) +
xlab("") + ylab("Number of Participants") +
geom_bar(stat = "identity")

youtube %>%
na.omit() %>%
gather(key = category, value = value, funny:use_sex) %>%
group_by(category,
year = 2 * (year %/% 2)) %>%
summarise(pct = mean(value), n = n()) %>%
ggplot(aes(x = year, y = pct, col = category)) +
geom_path(size = .9) +
scale_y_continuous(labels = percent) +
facet_wrap(~category) +
theme(legend.position = "none")

youtube %>%
na.omit() %>%
gather(key = category, value = value, funny:use_sex) %>%
group_by(category = str_to_title(str_replace_all(category, "_", " ")),
year = 2 * (year %/% 2)) %>%
summarise(pct = mean(value),
n = n()) %>%
ggplot(aes(x = year, y = pct, col = category)) +
geom_path(size = .9) +
scale_y_continuous(labels = percent) +
facet_wrap(~category) +
theme(legend.position = "none")

Testing Statistically
checking trend statistically related to year or not
glm(animals ~ year, family = "binomial", data = youtube) %>%
summary()
Statistically above relation doesn’t exist
glm(celebrity ~ year, family = "binomial", data = youtube) %>%
summary()
statistically year has relationship with celebrity
broom loops
Running loop on all using broom
youtube %>%
gather(category, value, funny:use_sex) %>%
group_by(category) %>%
nest()
youtube %>%
gather(category, value, funny:use_sex) %>%
group_by(category) %>%
summarise(model = list(glm(value ~ year, family = "binomial") )) %>%
mutate(td_modeldata = map(model, broom::tidy))
coefficients <- youtube %>%
# na.omit() %>%
gather(category, value, funny:use_sex) %>%
group_by(category) %>%
summarise(model = list(glm(value ~ year, family = "binomial") )) %>%
mutate(td_modeldata = map(model, broom::tidy)) %>%
unnest(td_modeldata) %>%
filter(term != "(Intercept)") %>%
arrange(desc(estimate))
coefficients
Categories with Only significant relationship with year
youtube %>%
na.omit() %>%
gather(key = category, value = value, funny:use_sex) %>%
group_by(category,
year = 2 * (year %/% 2)) %>%
summarise(pct = mean(value),
n = n()) %>%
inner_join(coefficients, by = "category") %>%
mutate(category = str_to_title(str_replace_all(category, "_", " "))) %>%
filter(p.value <= .01) %>%
ggplot(aes(x = year, y = pct, col = category)) +
geom_path(size = .9) +
scale_y_continuous(labels = percent) +
facet_wrap(~category) +
theme(legend.position = "none")

LS0tDQp0aXRsZTogIlRpZHkgdHVlc2RheSAtIFVuZW1wbG95bWVudCBFREEiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogeWVzDQogICAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvY19kZXB0aDogNg0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnNicNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQojIE9wdGlvbnMgJiBsaWJzDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgcmVzdWx0cz0naGlkZScsIGZpZy5rZWVwPSdhbGwnLCBkcGkgPSAzMDAsIGZpZy5oZWlnaHQgPSA2LCBmaWcud2lkdGggPSA2LCBvdXQud2lkdGggPSAiMTAwJSIsYXR0ci5vdXRwdXQ9J3N0eWxlPSJtYXgtaGVpZ2h0OiAzMDBweDsiJykNCmBgYA0KDQoNCg0KYGBge2NzcywgZWNobz1GQUxTRX0NCiMgQ1NTIGZvciBzY3JvbGxhYmxlIG91dHB1dCAmIEhlYWRlciBjb2xvcnMNCg0KLnNjcm9sbC0xMDAgew0KICBtYXgtaGVpZ2h0OiAxMDBweDsNCiAgb3ZlcmZsb3cteTogYXV0bzsNCiAgYmFja2dyb3VuZC1jb2xvcjogaW5oZXJpdDsNCn0NCg0KYGBgDQoNCg0KYGBge3J9DQojIFR1cm5pbmcgc2NpZW50aWZpYyAvIEV4cG9uZW50aWFsIG51bWJlcnMgb2ZmDQoNCm9wdGlvbnMoc2NpcGVuID0gOTk5KQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHRpZHl0dWVzZGF5UikNCmxpYnJhcnkoZ2d0aGVtZXMpDQpsaWJyYXJ5KGdsdWUpDQpsaWJyYXJ5KHNjYWxlcykNCmBgYA0KDQp2aWV3IG1pc3NpbmcgZGF0YQ0KDQpgYGB7cn0NCmxpYnJhcnkobmFuaWFyKQ0KYGBgDQoNCg0KQ3JlYXRpbmcgJiBzZXR0aW5nIGN1c3RvbSB0aGVtZQ0KDQpgYGB7cn0NCg0KdGhlbWVfdmlueV9icmlnaHQgPC0gZnVuY3Rpb24oKXsNCiAgDQogIGxpYnJhcnkoZ2d0aGVtZXMpDQogIA0KICBnZ3RoZW1lczo6dGhlbWVfZml2ZXRoaXJ0eWVpZ2h0KCkgJStyZXBsYWNlJQ0KICANCiAgdGhlbWUoDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksDQogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwNCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTAsIGZhY2UgPSAiYm9sZCIpLA0KICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDEsIHNpemUgPSA4KQ0KICAgICAgKQ0KICANCiAgfQ0KDQp0aGVtZV9zZXQodGhlbWVfdmlueV9icmlnaHQoKSkNCmBgYA0KDQoqKnNvdXJjZXM6KioNCg0KSW5zcGlyZWQgZnJvbTogaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1FSHFGRFhhLXNINCZ0PTIxMDVzDQoNCiMgTG9hZGluZyBkYXRhDQoNCmBgYHtyfQ0KdHQgPC0gdHRfbG9hZCgiMjAyMS0wMy0wMiIpDQp0dA0KYGBgDQoNCiMgRURBDQoNCmBgYHtyfQ0KeW91dHViZSA8LSB0dCR5b3V0dWJlDQp5b3V0dWJlDQpgYGANCg0KYGBge3J9DQpzdHIoeW91dHViZSkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkoeW91dHViZSkNCmBgYA0KDQpgYGB7cn0NCnlvdXR1YmUgJT4lIA0KICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCBhcy5mYWN0b3IpICU+JSANCiAgc3VtbWFyeSgpDQpgYGANCg0KbWlzc2luZyB2YWx1ZQ0KDQpgYGB7cn0NCm5hbmlhcjo6Z2dfbWlzc191cHNldChkYXRhID0geW91dHViZSkNCmBgYA0KDQoNCmBgYHtyfQ0KeW91dHViZSAlPiUgDQogIGNvdW50KGJyYW5kKSAlPiUgDQogIA0KICBtdXRhdGUoYnJhbmQgPSBmY3RfcmVvcmRlcihicmFuZCwgbikpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IG4sIHkgPSBicmFuZCkpICsNCiAgZ2VvbV9jb2woKQ0KYGBgDQoNCg0KYGBge3J9DQp5b3V0dWJlICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IHllYXIsIGZpbGwgPSBicmFuZCkpICsNCiAgZ2VvbV9iYXIoKSArDQogIGZhY2V0X3dyYXAofmJyYW5kKSArDQogIGd1aWRlcyh4ID0gZ3VpZGVfYXhpcyhuLmRvZGdlID0gMikpDQpgYGANCg0KYGBge3J9DQp5b3V0dWJlICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgbXV0YXRlKGJyYW5kID0gZmN0X3Jlb3JkZXIoYnJhbmQsIHZpZXdfY291bnQpKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSB2aWV3X2NvdW50LCB5ID0gYnJhbmQpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMykgKw0KICBzY2FsZV94X2xvZzEwKGxhYmVscyA9IGNvbW1hKQ0KYGBgDQoNCg0KYGBge3J9DQp5b3V0dWJlICU+JSANCiAgbmEub21pdCgpICU+JQ0KICBtdXRhdGUoYnJhbmQgPSBmY3RfcmVvcmRlcihicmFuZCwgdmlld19jb3VudCkpICU+JSANCiAgIA0KICBnZ3Bsb3QoYWVzKHggPSB2aWV3X2NvdW50LCB5ID0gYnJhbmQpKSArDQogIGdlb21fdmlvbGluKGRyYXdfcXVhbnRpbGVzID0gYygwLjI1LCAwLjUsIDAuNzUpKSArDQogIGdlb21faml0dGVyKGFscGhhID0gMC4zKSArDQogIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gY29tbWEpDQpgYGANCg0KYGBge3J9DQp5b3V0dWJlICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgbXV0YXRlKGJyYW5kID0gZmN0X3Jlb3JkZXIoYnJhbmQsIHZpZXdfY291bnQpKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSB2aWV3X2NvdW50LCB5ID0gYnJhbmQsIGZpbGwgPSBmdW5ueSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICAjIGdlb21faml0dGVyKGFscGhhID0gMC4zKSArDQogIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gY29tbWEpDQpgYGANCg0KDQpgYGB7cn0NCnlvdXR1YmUgJT4lIA0KICBuYS5vbWl0KCkgJT4lIA0KICBtdXRhdGUoYnJhbmQgPSBmY3RfcmVvcmRlcihicmFuZCwgdmlld19jb3VudCkpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IHZpZXdfY291bnQsIHkgPSBicmFuZCwgZmlsbCA9IHVzZV9zZXgpKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgIyBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMykgKw0KICBzY2FsZV94X2xvZzEwKGxhYmVscyA9IGNvbW1hKQ0KYGBgDQoNCg0KDQpgYGB7cn0NCnlvdXR1YmUgJT4lIGNvbG5hbWVzKCkNCmBgYA0KDQoNCmBgYHtyfQ0KeW91dHViZSAlPiUgDQogIHBpdm90X2xvbmdlcihuYW1lc190byA9ICJhZHNfY2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAidHJ1ZV9mYWxzZSIsIA0KICAgICAgICAgICAgICAgY29scyA9IGZ1bm55OnVzZV9zZXgpDQpgYGANCg0KIyMjIHBvcHVsYXIgY2F0ZWdvcmllcyBpbiBicmFuZHMNCg0KYGBge3J9DQp5b3V0dWJlICU+JSANCiAgcGl2b3RfbG9uZ2VyKG5hbWVzX3RvID0gImFkc19jYXRlZ29yeSIsIHZhbHVlc190byA9ICJ0cnVlX2ZhbHNlIiwgDQogICAgICAgICAgICAgICBjb2xzID0gZnVubnk6dXNlX3NleCkgJT4lIA0KICBmaWx0ZXIodHJ1ZV9mYWxzZSA9PSAiVFJVRSIpICU+JSANCiAgDQogIGdncGxvdChhZXMoeSA9IGFkc19jYXRlZ29yeSwgeCA9IHZpZXdfY291bnQpKSArDQogIGdlb21fY29sKCkgKw0KICBmYWNldF93cmFwKH5icmFuZCkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXRleHQpDQpgYGANCg0KIyMjIyBsb2cgb2Ygdmlld19jb3VudA0KDQpgYGB7cn0NCnlvdXR1YmUgJT4lIA0KICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiYWRzX2NhdGVnb3J5IiwgdmFsdWVzX3RvID0gInRydWVfZmFsc2UiLCANCiAgICAgICAgICAgICAgIGNvbHMgPSBmdW5ueTp1c2Vfc2V4KSAlPiUgDQogIGZpbHRlcih0cnVlX2ZhbHNlID09ICJUUlVFIikgJT4lIA0KICANCiAgZ2dwbG90KGFlcyh5ID0gZmN0X3Jlb3JkZXIoYWRzX2NhdGVnb3J5LCB2aWV3X2NvdW50KSwgDQogICAgICAgICAgICAgeCA9IHZpZXdfY291bnQpKSArDQogIGdlb21fY29sKCkgKw0KICBmYWNldF93cmFwKH5icmFuZCkgKw0KICBzY2FsZV94X2xvZzEwKCkNCmBgYA0KDQojIyMjIHJlb3JkZXJfd2l0aGluIGJ5IHZpZXdfY291bnQNCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQp5b3V0dWJlICU+JQ0KICBuYS5vbWl0KCkgJT4lIA0KICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiYWRzX2NhdGVnb3J5IiwgdmFsdWVzX3RvID0gInRydWVfZmFsc2UiLCANCiAgICAgICAgICAgICAgIGNvbHMgPSBmdW5ueTp1c2Vfc2V4KSAlPiUgDQogIGZpbHRlcih0cnVlX2ZhbHNlID09ICJUUlVFIiwNCiAgICAgICAgIHZpZXdfY291bnQgPiAxMDAwMCkgJT4lIA0KICBncm91cF9ieShicmFuZCwgYWRzX2NhdGVnb3J5LCB2aWV3X2NvdW50KSAlPiUgDQogIHN1bW1hcmlzZSh2aWV3X2NvdW50ID0gc3VtKHZpZXdfY291bnQpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGZhY3RvcikgJT4lIA0KICBtdXRhdGUoYWRzX2NhdGVnb3J5ID0gcmVvcmRlcl93aXRoaW4oeCA9IGFkc19jYXRlZ29yeSwgYnkgPSB2aWV3X2NvdW50LCB3aXRoaW4gPSBicmFuZCkpICU+JSANCiAgDQogIGdncGxvdChhZXMoeSA9IGFkc19jYXRlZ29yeSwgeCA9IHZpZXdfY291bnQpKSArDQogIGdlb21fY29sKCkgKw0KICBmYWNldF93cmFwKH5icmFuZCwgc2NhbGVzID0gImZyZWVfeSIpICsNCiAgc2NhbGVfeV9yZW9yZGVyZWQoKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSB1bml0X2Zvcm1hdCh1bml0ID0gIk0iLCBzY2FsZSA9IDFlLTYpKQ0KYGBgDQoNCmBgYHtyfQ0KZ2F0aGVyZWRfY2F0ZWdvcmllcyA8LSB5b3V0dWJlICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgZ2F0aGVyKGFkc19jYXRlZ29yeSwgdHJ1ZV9mYWxzZSwgZnVubnk6dXNlX3NleCkNCg0KZ2F0aGVyZWRfY2F0ZWdvcmllcw0KYGBgDQoNCiMjIyMgdmlld19jb3VudCBieSBwY3QNCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQpnYXRoZXJlZF9jYXRlZ29yaWVzICU+JSANCiAgZmlsdGVyKHRydWVfZmFsc2UgPT0gIlRSVUUiLA0KICAgICAgICAgKSAlPiUgIyB2aWV3X2NvdW50ID4gMTAwMDANCiAgDQogIGdyb3VwX2J5KGJyYW5kLCBhZHNfY2F0ZWdvcnkpICU+JSANCiAgc3VtbWFyaXNlKHZpZXdfY291bnQgPSBzdW0odmlld19jb3VudCkpICU+JSANCiAgDQogIGdyb3VwX2J5KGJyYW5kKSAlPiUgDQogIG11dGF0ZShwY3QgPSB2aWV3X2NvdW50IC8gc3VtKHZpZXdfY291bnQpKSAlPiUgDQogIA0KICAjIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGZhY3RvcikgJT4lIA0KICBtdXRhdGUoYWRzX2NhdGVnb3J5ID0gcmVvcmRlcl93aXRoaW4oeCA9IGFkc19jYXRlZ29yeSwgYnkgPSBwY3QsIHdpdGhpbiA9IGJyYW5kKSkgJT4lIA0KICANCiAgZ2dwbG90KGFlcyh5ID0gYWRzX2NhdGVnb3J5LCB4ID0gdmlld19jb3VudCkpICsNCiAgZ2VvbV9jb2woKSArDQogIGZhY2V0X3dyYXAofmJyYW5kLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBzY2FsZV95X3Jlb3JkZXJlZCgpICsNCiAgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSB1bml0X2Zvcm1hdCh1bml0ID0gIk0iLCBzY2FsZSA9IDFlLTYpKQ0KYGBgDQoNCg0KIyMjIyBieSBwY3QNCg0Kd3JhcHBpbmcgYXhpcyB0ZXh0IHVzaW5nIHN0cl93cmFwKCkgZnJvbTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjE4Nzg5NzQvd3JhcC1sb25nLWF4aXMtbGFiZWxzLXZpYS1sYWJlbGxlci1sYWJlbC13cmFwLWluLWdncGxvdDINCg0KYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9MTB9DQpnYXRoZXJlZF9jYXRlZ29yaWVzICU+JSANCiAgZmlsdGVyKHRydWVfZmFsc2UgPT0gIlRSVUUiLA0KICAgICAgICAgKSAlPiUgIyB2aWV3X2NvdW50ID4gMTAwMDANCiAgDQogIGdyb3VwX2J5KGJyYW5kLCBhZHNfY2F0ZWdvcnkpICU+JSANCiAgc3VtbWFyaXNlKHZpZXdfY291bnQgPSBzdW0odmlld19jb3VudCkpICU+JSANCiAgDQogIGdyb3VwX2J5KGJyYW5kKSAlPiUgDQogIG11dGF0ZShwY3QgPSB2aWV3X2NvdW50IC8gc3VtKHZpZXdfY291bnQpLA0KICAgICAgICAgYWRzX2NhdGVnb3J5ID0gc3RyX3JlcGxhY2VfYWxsKGFkc19jYXRlZ29yeSwiXyIsIiAiKSwNCiAgICAgICAgIGFkc19jYXRlZ29yeSA9IHN0cl93cmFwKGFkc19jYXRlZ29yeSwgd2lkdGggPSAxMCkpICU+JSANCiAgDQogICMgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgZmFjdG9yKSAlPiUgDQogIG11dGF0ZShhZHNfY2F0ZWdvcnkgPSByZW9yZGVyX3dpdGhpbih4ID0gYWRzX2NhdGVnb3J5LCBieSA9IHBjdCwgd2l0aGluID0gYnJhbmQpDQogICAgICAgICApICU+JQ0KICANCiAgZ2dwbG90KGFlcyh5ID0gYWRzX2NhdGVnb3J5LCB4ID0gcGN0KSkgKw0KICBnZW9tX2NvbCgpICsNCiAgZmFjZXRfd3JhcCh+YnJhbmQsIHNjYWxlcyA9ICJmcmVlX3kiKSArDQogIHNjYWxlX3lfcmVvcmRlcmVkKCkgKw0KICANCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpDQpgYGANCg0KIyMjIyBwY3Qrdmlld19jb3VudCBsYWJlbHMNCg0KQWRkaW5nIHZpZXdfY291bnQgdG8gYXhpcyB0ZXh0IGluIGFib3ZlIGNoYXJ0DQoNCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEwfQ0KZ2F0aGVyZWRfY2F0ZWdvcmllcyAlPiUgDQogIGZpbHRlcih0cnVlX2ZhbHNlID09ICJUUlVFIiwNCiAgICAgICAgICkgJT4lICMgdmlld19jb3VudCA+IDEwMDAwDQogIA0KICBncm91cF9ieShicmFuZCwgYWRzX2NhdGVnb3J5KSAlPiUgDQogIHN1bW1hcmlzZSh2aWV3X2NvdW50ID0gc3VtKHZpZXdfY291bnQpKSAlPiUgDQogIA0KICBncm91cF9ieShicmFuZCkgJT4lIA0KICBtdXRhdGUocGN0ID0gdmlld19jb3VudCAvIHN1bSh2aWV3X2NvdW50KSwNCiAgICAgICAgIGFkc19jYXRlZ29yeSA9IHN0cl9yZXBsYWNlX2FsbChhZHNfY2F0ZWdvcnksIl8iLCIgIiksDQogICAgICAgICBhZHNfY2F0ZWdvcnkgPSBwYXN0ZShhZHNfY2F0ZWdvcnksdmlld19jb3VudCksDQogICAgICAgICBhZHNfY2F0ZWdvcnkgPSBzdHJfd3JhcChhZHNfY2F0ZWdvcnksIHdpZHRoID0gMTApKSAlPiUgDQogIA0KICAjIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGZhY3RvcikgJT4lIA0KICBtdXRhdGUoYWRzX2NhdGVnb3J5ID0gcmVvcmRlcl93aXRoaW4oeCA9IGFkc19jYXRlZ29yeSwgYnkgPSBwY3QsIHdpdGhpbiA9IGJyYW5kKQ0KICAgICAgICAgKSAlPiUNCiAgDQogIGdncGxvdChhZXMoeSA9IGFkc19jYXRlZ29yeSwgeCA9IHBjdCkpICsNCiAgZ2VvbV9jb2woKSArDQogIGZhY2V0X3dyYXAofmJyYW5kLCBzY2FsZXMgPSAiZnJlZV95IikgKw0KICBzY2FsZV95X3Jlb3JkZXJlZCgpICsNCiAgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KQ0KYGBgDQoNCmBgYHtyfQ0KdGVzdF9zZXQgPSBkYXRhLmZyYW1lKHggPSBjKCJsYWJlbCIsICJsb25nIGxhYmVsIiwgInZlcnksX3ZlcnlfbG9uZ19sYWJlbCIpLCANCiAgICAgICAgICAgICAgICB5ID0gYygxMCwgMTUsIDIwKSkNCg0KdGVzdF9zZXQkbmV3eCA9IHN0cl93cmFwKHRlc3Rfc2V0JHgsIHdpZHRoID0gMTApDQoNCmdncGxvdCh0ZXN0X3NldCwgYWVzKG5ld3gsIHkpKSArIA0KICB4bGFiKCIiKSArIHlsYWIoIk51bWJlciBvZiBQYXJ0aWNpcGFudHMiKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKQ0KYGBgDQoNCg0KYGBge3J9DQp5b3V0dWJlICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgZ2F0aGVyKGtleSA9IGNhdGVnb3J5LCB2YWx1ZSA9IHZhbHVlLCBmdW5ueTp1c2Vfc2V4KSAlPiUgDQogIA0KICBncm91cF9ieShjYXRlZ29yeSwNCiAgICAgICAgICAgeWVhciA9IDIgKiAoeWVhciAlLyUgMikpICU+JSANCiAgc3VtbWFyaXNlKHBjdCA9IG1lYW4odmFsdWUpLCBuID0gbigpKSAlPiUgDQogIA0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gcGN0LCBjb2wgPSBjYXRlZ29yeSkpICsNCiAgZ2VvbV9wYXRoKHNpemUgPSAuOSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKw0KICBmYWNldF93cmFwKH5jYXRlZ29yeSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpgYGANCg0KDQpgYGB7cn0NCnlvdXR1YmUgJT4lIA0KICBuYS5vbWl0KCkgJT4lIA0KICBnYXRoZXIoa2V5ID0gY2F0ZWdvcnksIHZhbHVlID0gdmFsdWUsIGZ1bm55OnVzZV9zZXgpICU+JSANCiAgDQogIGdyb3VwX2J5KGNhdGVnb3J5ID0gc3RyX3RvX3RpdGxlKHN0cl9yZXBsYWNlX2FsbChjYXRlZ29yeSwgIl8iLCAiICIpKSwNCiAgICAgICAgICAgeWVhciA9IDIgKiAoeWVhciAlLyUgMikpICU+JSANCiAgc3VtbWFyaXNlKHBjdCA9IG1lYW4odmFsdWUpLCANCiAgICAgICAgICAgIG4gPSBuKCkpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBwY3QsIGNvbCA9IGNhdGVnb3J5KSkgKw0KICBnZW9tX3BhdGgoc2l6ZSA9IC45KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArDQogIGZhY2V0X3dyYXAofmNhdGVnb3J5KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQoNCiMjIFRlc3RpbmcgU3RhdGlzdGljYWxseQ0KDQpjaGVja2luZyB0cmVuZCBzdGF0aXN0aWNhbGx5IHJlbGF0ZWQgdG8geWVhciBvciBub3QgDQoNCmBgYHtyfQ0KZ2xtKGFuaW1hbHMgfiB5ZWFyLCBmYW1pbHkgPSAiYmlub21pYWwiLCBkYXRhID0geW91dHViZSkgJT4lIA0KICBzdW1tYXJ5KCkNCmBgYA0KDQpTdGF0aXN0aWNhbGx5IGFib3ZlIHJlbGF0aW9uIGRvZXNuJ3QgZXhpc3QNCg0KYGBge3J9DQpnbG0oY2VsZWJyaXR5IH4geWVhciwgZmFtaWx5ID0gImJpbm9taWFsIiwgZGF0YSA9IHlvdXR1YmUpICU+JSANCiAgc3VtbWFyeSgpDQpgYGANCg0Kc3RhdGlzdGljYWxseSB5ZWFyIGhhcyByZWxhdGlvbnNoaXAgd2l0aCBjZWxlYnJpdHkgDQoNCiMjIyBicm9vbSBsb29wcw0KDQpSdW5uaW5nIGxvb3Agb24gYWxsIHVzaW5nIGJyb29tDQoNCmBgYHtyfQ0KeW91dHViZSAlPiUgDQogIGdhdGhlcihjYXRlZ29yeSwgdmFsdWUsIGZ1bm55OnVzZV9zZXgpICU+JSANCiAgZ3JvdXBfYnkoY2F0ZWdvcnkpICU+JSANCiAgbmVzdCgpDQpgYGANCg0KDQpgYGB7cn0NCnlvdXR1YmUgJT4lIA0KICBnYXRoZXIoY2F0ZWdvcnksIHZhbHVlLCBmdW5ueTp1c2Vfc2V4KSAlPiUgDQogIGdyb3VwX2J5KGNhdGVnb3J5KSAlPiUgDQogIHN1bW1hcmlzZShtb2RlbCA9IGxpc3QoZ2xtKHZhbHVlIH4geWVhciwgZmFtaWx5ID0gImJpbm9taWFsIikgKSkgJT4lIA0KICBtdXRhdGUodGRfbW9kZWxkYXRhID0gbWFwKG1vZGVsLCBicm9vbTo6dGlkeSkpDQpgYGANCg0KYGBge3J9DQpjb2VmZmljaWVudHMgPC0gIHlvdXR1YmUgJT4lIA0KICAjIG5hLm9taXQoKSAlPiUgDQogIGdhdGhlcihjYXRlZ29yeSwgdmFsdWUsIGZ1bm55OnVzZV9zZXgpICU+JSANCiAgZ3JvdXBfYnkoY2F0ZWdvcnkpICU+JSANCiAgc3VtbWFyaXNlKG1vZGVsID0gbGlzdChnbG0odmFsdWUgfiB5ZWFyLCBmYW1pbHkgPSAiYmlub21pYWwiKSApKSAlPiUgDQogIG11dGF0ZSh0ZF9tb2RlbGRhdGEgPSBtYXAobW9kZWwsIGJyb29tOjp0aWR5KSkgJT4lIA0KICB1bm5lc3QodGRfbW9kZWxkYXRhKSAlPiUgDQogIGZpbHRlcih0ZXJtICE9ICIoSW50ZXJjZXB0KSIpICU+JSANCiAgYXJyYW5nZShkZXNjKGVzdGltYXRlKSkNCg0KY29lZmZpY2llbnRzDQpgYGANCg0KQ2F0ZWdvcmllcyB3aXRoIE9ubHkgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIHdpdGggeWVhciANCg0KYGBge3J9DQp5b3V0dWJlICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgZ2F0aGVyKGtleSA9IGNhdGVnb3J5LCB2YWx1ZSA9IHZhbHVlLCBmdW5ueTp1c2Vfc2V4KSAlPiUgDQogIA0KICBncm91cF9ieShjYXRlZ29yeSwNCiAgICAgICAgICAgeWVhciA9IDIgKiAoeWVhciAlLyUgMikpICU+JSANCiAgc3VtbWFyaXNlKHBjdCA9IG1lYW4odmFsdWUpLCANCiAgICAgICAgICAgIG4gPSBuKCkpICU+JSANCiAgDQogIGlubmVyX2pvaW4oY29lZmZpY2llbnRzLCBieSA9ICJjYXRlZ29yeSIpICU+JSANCiAgbXV0YXRlKGNhdGVnb3J5ID0gc3RyX3RvX3RpdGxlKHN0cl9yZXBsYWNlX2FsbChjYXRlZ29yeSwgIl8iLCAiICIpKSkgJT4lIA0KICBmaWx0ZXIocC52YWx1ZSA8PSAuMDEpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBwY3QsIGNvbCA9IGNhdGVnb3J5KSkgKw0KICBnZW9tX3BhdGgoc2l6ZSA9IC45KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArDQogIGZhY2V0X3dyYXAofmNhdGVnb3J5KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQoNCg0KDQo=